home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / debugtrc.zip / DEBUGTRC.C < prev   
Text File  |  1993-01-04  |  5KB  |  214 lines

  1.  
  2.  
  3. calltrace(arg_1)                /*  Trace calling sequence  */
  4.     {
  5.     int *bp, *newbp;
  6.  
  7.     bp = (int *) (&arg_1 - 2);
  8.  
  9.     while (bp < stacktop)   /*  "<" because STACKLOW  */
  10.         {
  11.         newbp = (int *) *bp;    /*  next link in list  */
  12.         printf("BP=%08lx  RET. ADDR=%08lx\n", bp, *(bp + 1));
  13.         bp = newbp;
  14.         }
  15.     }
  16.  
  17.  
  18.  
  19. [LISTING FOUR]
  20.  
  21.  
  22. struct func
  23.     {
  24.     int (*addr)();
  25.     char *name;
  26.     };
  27.  
  28. int main(), f(), g();
  29.  
  30. struct func funcs[] =           /*  symbol table  */
  31.     {
  32.     main, "main",
  33.     f, "f",
  34.     g, "g",
  35.     };
  36.  
  37. int nfuncs = sizeof(funcs)/sizeof(funcs[0]);
  38.  
  39. char *atoname(a)        /*  convert address to function name  */
  40. int (*a)();             /*  address  */
  41.     {
  42.     char *s;
  43.     int (*maxa)();
  44.     int n;
  45.  
  46.     maxa = 0;
  47.     s = "?";
  48.     for (n = 0; n < nfuncs; n++)
  49.             if (funcs[n].addr < a && funcs[n].addr > maxa)
  50.                     s = funcs[n].name, maxa = funcs[n].addr;
  51.     return s;
  52.     }
  53.  
  54.  
  55. Example 1: Defining the NDEBUG macro
  56.  
  57.         #ifndef NDEBUG
  58.         #define assert(cond) {if (!(cond)) \
  59.             printf("ASSERT cond,  file %s line %d\n", \
  60.             __FILE__, __LINE__); exit(1);}
  61.         #else
  62.         #define assert(cond) {;}  /*  Empty block  */
  63.         #endif
  64.  
  65.  
  66. Example 2: Using an assertion 
  67.  
  68.         do_str(s)
  69.         char *s;
  70.             {
  71.             assert(s != NULL)
  72.             /*  rest of do_str...  */
  73.  
  74.  
  75.  
  76. Example 3: using parentheses so that the entire arugment list to 
  77. printf is a single argument
  78.  
  79.         #define assertp(cond, args)     {if (!(cond)) \
  80.             printf("ASSERT cond, file %s, line %d\n", \
  81.             __FILE__, __LINE__); \
  82.             printf args; exit(1);}
  83.  
  84.  
  85. Example 4: A typical use of assert
  86.  
  87.         assertp(n > 3, ("Surprise! n > 3, is %d\n", n))
  88.  
  89.  
  90. Example 5: A macro which unconditionally prints when the trace 
  91. level is high enough
  92.  
  93.         #define assertl(level, args)    {if (tlevel >= (level)) \
  94.             printf("file %s, line %d\n", \
  95.             __FILE__, __LINE__); \
  96.             printf args; exit(1);}
  97.  
  98.  
  99. Example 6: A typical use of Example 5
  100.  
  101.         assertl(2, ("i=%d j=%d\n", i, j))
  102.  
  103.  
  104. Example 7: An assert.h header file
  105.  
  106.         #ifndef NDEBUG
  107.         extern short tlevel;
  108.         #define main    mymain
  109.         #endif
  110.  
  111.  
  112. Example 8: Typical bit definitions 
  113.  
  114.         #define TBIT_LEXER   0x0001 /* Lexical analysis functions 
  115. */
  116.         #define TBIT_PARSER  0x0002 /* Parser  */
  117.         #define TBIT_EXPTREE 0x0004 /* Expression tree  */
  118.         #define TBIT_CODEGEN 0x0008 /* Code generator  */
  119.         #define TBIT_OPTIM   0x0010 /* Optimizer  */
  120.  
  121.  
  122. Example 9: Defining assert-like macros
  123.  
  124.             #define assertb(bits, args)     {if ((bits) & tbits)
  125. \
  126.                     printf args;}
  127.  
  128. which can be used in this way:
  129.  
  130.         assertb(TBITS_PARSER | TBITS_EXPTREE,
  131.             ("Nodes in expression tree = %d\n", nnode))
  132.  
  133.  
  134. Example 10: Adding a statement to trap an error
  135.  
  136.         do_str(s)
  137.         char *s;
  138.             {
  139.             if (s == NULL)
  140.                  printf("do_str(NULL)!\n");
  141.  
  142.  
  143. Example 11: A function for a calling function 
  144.  
  145.         do_str(s)
  146.         char *s;
  147.             {
  148.             char *caller();
  149.             if (s == NULL)
  150.                 printf("%s() calls do_str(NULL)\n", caller());
  151.             }
  152.  
  153.  
  154. Example 12: Calling a function
  155.  
  156.  
  157.         push n'th argument
  158.         ...
  159.         push 2nd argument
  160.         push 1st argument
  161.         push current instruction pointer (ie. return address)
  162.         jump to start of function
  163.         copy stack pointer (SP) to base pointer (BP)
  164.         push BP
  165.  
  166.  
  167. Example 13: The top of the stack after functions have been called
  168.     
  169.               2nd arg
  170.               1st arg
  171.               Return addr.
  172.         BP--> Caller's BP
  173.    
  174.  
  175. Example 14: Modifying showstack so that g() calls only ctrace() 
  176. results in this output
  177.  
  178.     &main=00000094  &f=000000db  &g=000000f9
  179.     BP=0187ed20  RET. ADDR=0000010a
  180.     BP=0187ed38  RET. ADDR=000000f1
  181.     BP=0187ed50  RET. ADDR=000000d3
  182.     BP=0187ed6c  RET. ADDR=0000057d
  183.  
  184.  
  185. Example 15: The function atoname() finds the function closest to, 
  186. but starting before, the address given as its argument. 
  187.  
  188.         printf("BP=%08lx  FUNCTION=%s\n", bp, atoname(*(bp + 1)));
  189.  
  190. then the output looks like this:
  191.  
  192.         &main=00000094  &f=000000db  &g=000000f9
  193.         BP=0187ed28  FUNCTION=g
  194.         BP=0187ed40  FUNCTION=f
  195.         BP=0187ed58  FUNCTION=main
  196.         BP=0187ed74  FUNCTION=g
  197.  
  198.  
  199. Example 16: Changing ctrace() again
  200.  
  201.         printf("%s(%x, %x)\n", atoname(*(bp + 1)), *(newbp + 2),
  202. *(newbp + 3));
  203.  
  204. After this change, the output of the test program became:
  205.  
  206.         &main=00000094  &f=000000db  &g=000000f9
  207.         g(55556666, 187eda8)
  208.         f(11112222, 33334444)
  209.         main(1, 187eda8)
  210.         g(1, 187ee20)
  211.  
  212. _DEBUGGING C PROGRAMS_
  213. by Bob Edgar
  214.